﻿using AutoMapper;
using DataServer.ApplicationLib.Entities;
using DataServer.ApplicationLib.Repositories;
using DataServer.ApplicationLib.Rules;
using DataServer.CommonLib.Models.ConfigData;
using DataServer.CommonLib.Models.DataConfig;
using Swimj.CommonLib.Base;
using System.Data;
using Swimj.Core.Securities;
using Swimj.DataCore;

namespace DataServer.ApplicationLib.Services
{
    public class ConfigDataService : IConfigDataService
    {
        private readonly IConfigDataRepository _configDataRepository;
        private readonly IDataConfigRepository _dataConfigRepository;
        private readonly IConfigFieldRepository _configFieldRepository;
        private readonly IConfigRuleRepository _configRuleRepository;
        private readonly IUnitOfWork _unitOfWork;
        private readonly IServiceProvider _serviceProvider;
        private readonly ISecurityUser _securityUser;
        private readonly IMapper _mapper;

        public ConfigDataService(IConfigDataRepository configDataRepository,
            IDataConfigRepository dataConfigRepository,
            IConfigFieldRepository configFieldRepository,
            IConfigRuleRepository configRuleRepository,
            IUnitOfWork unitOfWork,
            IServiceProvider serviceProvider,
            ISecurityUser securityUser,
            IMapper mapper)
        {
            _configDataRepository = configDataRepository;
            _dataConfigRepository = dataConfigRepository;
            _configFieldRepository = configFieldRepository;
            _configRuleRepository = configRuleRepository;
            _unitOfWork = unitOfWork;
            _serviceProvider = serviceProvider;
            _securityUser = securityUser;
            _mapper = mapper;
        }

        public async Task<Result<ConfigDataInfoResponseDto>> CreateAsync(IDictionary<string, object> model)
        {
            if (!model.ContainsKey("ConfigCode"))
            {
                return await Result<ConfigDataInfoResponseDto>.FailAsync("");
            }

            var configCode = model["ConfigCode"].ToString();
            if (string.IsNullOrWhiteSpace(configCode))
            {
                return await Result<ConfigDataInfoResponseDto>.FailAsync("");
            }

            var dataConfig = await _dataConfigRepository.GetByCodeAsync(configCode);

            var configFields = await _configFieldRepository.QueryFieldsByConfigAsync(configCode, new ConfigFieldSearchRequestDto());

            var configRules = await _configRuleRepository.QueryRulesByConfigAsync(configCode, new ConfigRuleSearchRequestDto());

            DataTable dataTable = new DataTable();
            dataTable.Columns.Add(new DataColumn()
            {
                ColumnName = "ConfigId",
                DataType = typeof(Guid),
            });
            dataTable.Columns.AddRange(model.Keys.Select(i => new DataColumn()
            {
                ColumnName = i
            }).ToArray());
            var dataRow = dataTable.NewRow();
            dataRow["ConfigId"] = dataConfig.Id;
            foreach (var item in model)
            {
                dataRow[item.Key] = item.Value;
            }
            dataTable.Rows.Add(dataRow);

            // 创建规则
            var rule = ConfigDataRuleFactory.CreateConfigDataRule(new ConfigDataCreateRuleRequest()
            {
                EnableFieldRule = true,
                EnableRowRule = true,
                EnablePrimaryKeyRule = true,
                EnableTableRule = true
            }, new RuleContext()
            {
                TargetData = dataTable,
                ConfigInfo = dataConfig,
                ConfigRuleInfos = configRules,
                ConfigFieldInfos = configFields,
                CurUserOpType = UserOperationType.Add,
                ServiceProvider = _serviceProvider,
                CurrentUserName = _securityUser.GetUserId()?.ToString()
            });

            // 通过规则校验数据
            var verifyResult = await rule.VerifyData();

            if (verifyResult is { IsValid: true })
            {
                var configDataEntities = _mapper.Map<IDataReader, IEnumerable<ConfigDataEntity>>(dataTable.CreateDataReader());

                await _configDataRepository.BatchInsertAsync(configDataEntities);

                _unitOfWork.Commit();

            }

            return await Result<ConfigDataInfoResponseDto>.SuccessAsync(
                _mapper.Map<ConfigDataInfoResponseDto>(null));
        }

        public async Task<Result<IList<ConfigDataInfoResponseDto>>> QueryConfigDatasAsync(ConfigDataSearchRequestDto model)
        {
            var conditionCollection = new ConditionCollection();
            if (model != null)
            {

            }

            var result = await _configDataRepository.QueryFilterAsync(conditionCollection);
            return await Result<IList<ConfigDataInfoResponseDto>>.SuccessAsync(
                _mapper.Map<List<ConfigDataInfoResponseDto>>(result));
        }

        public async Task<PaginatedResult<ConfigDataInfoResponseDto>> QueryConfigDatasByPageAsync(ConfigDataSearchRequestDto model)
        {
            var conditionCollection = new ConditionCollection();
            if (model != null)
            {

                var result =
                    await _configDataRepository.QueryFilterByPageAsync(conditionCollection, model.Page, model.Limit);

                return await PaginatedResult<ConfigDataInfoResponseDto>.SuccessAsync(
                    _mapper.Map<List<ConfigDataInfoResponseDto>>(result.Item1),
                    result.Item2,
                    model.Page, model.Limit);
            }

            return await PaginatedResult<ConfigDataInfoResponseDto>.SuccessAsync(new List<ConfigDataInfoResponseDto>(),
                0, 0, 0);
        }
    }
}